﻿@using Resource;
@{
    Layout = null;
}

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no" />
    <meta http-equiv="Expires" content="0">
    <meta http-equiv="Pragma" content="no-cache">
    <meta http-equiv="Cache-control" content="no-cache">
    <meta http-equiv="Cache" content="no-cache">
    @{
        await Html.RenderPartialAsync("/Views/Shared/_LayoutScript.cshtml");
    }
    @{
        await Html.RenderPartialAsync("/Views/Shared/_StyleCss.cshtml");
    }
    <script src="/lib/xlsx/xlsx.full.min.js?v=@DateTime.Now.Ticks"></script>
    <link href="/css/TsyaReport.css?v=@DateTime.Now.Ticks" rel="stylesheet" />
    <title>TsyaReport</title>
    <style type="text/css">
        /*报表样式*/
        html, body {
            background: url(../images/ProcessCapacity/bgwhite.png) no-repeat;
            background-size: cover;
            font-size: .16rem;
            color: #ffffff;
            /* position: relative; */
            width: 100%;
            height: 100%;
            font-family: myFirstFont !important;
            color: black;
        }

        #report_center {
            height: calc(100vh - 0.7rem);
            width: 100%
        }

        .report_table {
            height: calc(100% / 3);
            width: 100%;
        }

        .table{
            box-sizing: border-box;
            border: 1px solid #0bc4e9;
            height: calc(100% - 0.05rem);
            width: calc(60% - 0.1rem);
            float: left;
            /* padding: 0.05rem; */
            margin: 0rem 0.05rem 0rem 0.05rem;
            overflow: auto;
            position: relative;
        }

        .chart {
            box-sizing: border-box;
            border: 1px solid #0bc4e9;
            height: calc(100% - 0.05rem);
            width: calc(40% - 0.05rem);
            float: left;
            /* padding: 0.05rem; */
            margin: 0.05rem,0.05rem,0rem,0rem;
        }

        [id$="_grid"]  {
            white-space: nowrap;
            margin: 0;
            border: none;
            border-collapse: collapse;
        }

        [id$="_grid"] th, 
        [id$="_grid"] td {
            border: 1px solid #eee;
            min-width: 0.7rem;
            text-align: center;
            font-size: 0.13rem;
        }

        [id$="_grid"] td.cell-warn {
            background-color: #f5fd02;
            color: red;
        }

        [id$="_grid"] thead th {
            position: sticky;
            top: -1px;
            background-color: #eeecec;
            z-index: 2;
        }

        [id$="_grid"] th:first-child,
        [id$="_grid"] td:first-child {
            position: sticky;
            left: -1px;
            background-color: #eee;
            z-index: 1;
        }

        [id$="_grid"] thead th:first-child {
            background-color: #d0e3f0;
            font-weight: bolder;
            z-index: 3;
        }

        [id$="_grid"] tfoot {
            font-size: 0.13rem;
            position: sticky;
            bottom: -1px;
            z-index: 3;
            background-color: #ffddc4;
        }

        [id$="_grid"] tfoot tr,
        [id$="_grid"] tfoot tr td {
            height: 0.4rem;
            border: none;
        }

        /*明细模态*/
        .mode_confirm {
            border-radius: 0.1rem;
            position: absolute;
            z-index: 99;
            height: 100vh;
            width: 100vw;
            background: #ffffff;
            display: none;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
        }

        .mode_confirm > .mode_detail > div > label {
            color: black;
        }

        .detail {
            color: black;
            background-color: #f7fdff;
            height: 3rem;
            width: 100%;
        }

        .mode_close {
            color: #007bff;
            float: right;
            font-size: 0.18rem;
            font-weight: bold;
            margin: 0.1rem 0;
            padding: 3px 3px 0px 0px;
        }

        .mode_close:hover {
            color:red;
            font-size: 0.2rem;
            font-weight: bold;
        }

        /*end*/

        .mode_detail{
            height: calc((100% - 0.65rem) * (1/3));
            width: calc(100% - 0.2rem);
            margin: 0 auto;
            margin: 0 0.1rem;
            /* border: 1px solid red; */
        }

    </style>
</head>
<body class="fill-parent" style="overflow-y: hidden; color: black;">
    <div class="main">
        <div class="center">
            <div class="center-left fl">
                <div class="left-top">
                    <div class="query">
                        <span class="titleinput tle">@Label.Time:</span>
                        <input type="date" id="startdate" name="startdate" placeholder="@Label.Start@Label.Time">
                        <span class="titleinput tle">@Label.To</span>
                        <input type="date" id="enddate" name="enddate" placeholder="@Label.Start@Label.End">
                        <span class="titleinput tle">Site:</span>
                        <select id="cmb_site" name="Site" placeholder="select Site">
                            <option value="DG">@Label.DG</option>
                            <option value="AMT">@Label.AMT</option>
                        </select>
                        <span class="titleinput tle">Project:</span>
                        <select id="cmb_projcode" placeholder="select Project" style="width: 1.9rem;">
                            <option value="ALL">ALL</option>
                            @* <option value="ALL">@Label.PleaseSelect</option> *@
                        </select>
                        <button id="btn_query" class="btn btn-primary  btn-sm col-md-12" type="button" onclick="getdate()">@Label.Query</button>
                        <div class="tab tab-chart">
                            <button class="tablinks active" onclick="OpenTab(event,'tab-chart','fpy-chart',OutputPlanTab,'202506')">Prime&nbsp;Yield </button>
                            <button class="tablinks" onclick="OpenTab(event,'tab-chart','fpy-chart',OutputPlanTab,'202506')">Final&nbsp;Yield </button>
                            <button class="tablinks" onclick="OpenTab(event,'tab-chart','fpy-chart',OutputPlanTab,'202506')">Gap&nbsp;Yield </button>
                        </div>
                    </div>
                    <div id="report_center">
                        <div class="report_table">
                            <div id="prime_table" class="table"></div>
                            <div id="prime_chart" class="chart"></div>
                        </div>
                        <div class="report_table ">
                            <div id="final_table" class="table"></div>
                            <div id="final_chart" class="chart"></div>
                        </div>
                        <div class="report_table">
                            <div id="gap_table" class="table"></div>
                            <div id="gap_chart" class="chart"></div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
        <div class="mode_confirm">
            <span class="mode_close">关闭×</span>
            <div style="height: 0.3rem; margin: 0.15rem 0;">
                <span class="process_name" style="font-size:0.25rem;color:#007bff;font-weight:bold;line-height:0.3rem;padding-left: 0.15rem;"></span>
            </div>
            <div class="mode_detail" id="inputchart"></div>
            <div class="mode_detail" id="failuremodechart"></div>
            <div class="mode_detail" id="testeryieldchart"></div>
        </div>

    </div>

    <script type="text/javascript" href="?v=@DateTime.Now.Ticks">
        $(".mode_confirm").css("display", "none");
        $('.mode_close').click(function () {
            $(".mode_confirm").css("display", "none");
            //$(".mode_detail").empty();
        });
        $(document).ready(function () {
            var whei = $(window).height();
            $("html").css({ fontSize: whei / 12.5 });
            $(window).resize(function () {
                if ($(".dimension").text() == "@Html.Raw(Label.Full)") {
                    var whei = $(window).height();
                    $("html").css({ fontSize: whei / 12.5 });
                }
                else {
                    var whei = $(window).width();
                    $("html").css({ fontSize: whei / 22 })
                }
            });
            // 设置全屏
            $('.dimension').on('click', function (e) {
                var element = document.documentElement;
                if ($(".dimension").text() == "@Html.Raw(Label.Full)") {
                    // 判断浏览器设备类型
                    if (element.requestFullscreen) {
                        element.requestFullscreen();
                    } else if (element.mozRequestFullScreen) {       //兼容火狐
                        element.mozRequestFullScreen();
                    } else if (element.webkitRequestFullscreen) {    //兼容谷歌
                        element.webkitRequestFullscreen();
                    } else if (element.msRequestFullscreen) {        //兼容IE
                        element.msRequestFullscreen();
                    }
                    $(".dimension").text("@Html.Raw(Label.Exit + Label.Full)");
                } else {
                    if (document.exitFullscreen) {
                        document.exitFullscreen();
                    } else if (document.mozCancelFullScreen) {
                        document.mozCancelFullScreen();
                    } else if (document.webkitCancelFullScreen) {
                        document.webkitCancelFullScreen();
                    } else if (document.msExitFullscreen) {
                        document.msExitFullscreen();
                    }
                    $(".dimension").text("@Html.Raw(Label.Full)");
                }
            });

            $('#btn_query').prop('disabled', true);
            $('#startdate').on('change', function () {
                var startDate = new Date($(this).val());
                var endDate = new Date($('#enddate').val());
                startDate.setDate(startDate.getDate() + 1);
                var minEndDate = startDate.toISOString().split('T')[0];
                $('#enddate').attr('min', minEndDate);
                if (endDate < startDate) {
                    $('#enddate').val($(this).val());
                }
            });
            $('#enddate').on('change', function () {
                var startDate = new Date($('#startdate').val());
                var endDate = new Date($(this).val());
                endDate.setDate(endDate.getDate() - 1);
                var maxStartDate = endDate.toISOString().split('T')[0];
                $('#startdate').attr('max', maxStartDate);
                if (startDate > endDate) {
                    $('#startdate').val($(this).val());
                }
            });

            var startDate = new Date();
            startDate.setMonth(startDate.getMonth() - 1);
            startDate.setHours(0, 0, 0, 0);
            var endDate = new Date();
            endDate.setHours(0, 0, 0, 0);
            $('#startdate').val(startDate.toISOString().split('T')[0]);
            $('#enddate').val(endDate.toISOString().split('T')[0]);
        });

        function loadingshow() {
            $('#btn_query').prop('disabled', false);
            $('tfoot').css('background-color', 'transparent');
            $('.table,.chart').css('background-image', 'url("../images/loading.gif")');
            $('.table,.chart').css('background-size', '0.8rem 0.8rem');
            $('.table,.chart').css('background-repeat', 'no-repeat');
            $('.table,.chart').css('background-position', 'center');
        }
        function loadingnone() {
            $('#btn_query').prop('disabled', false);
            $('tfoot').css('background-color', '#09314e');
            $('.table,.chart').css('background-image', 'none');
        }

        /*下拉框*/
        $(function () {
            var projectsele = $("#cmb_projcode");
            var startdate = $("#startdate").val();
            var enddate = $("#enddate").val();
            var pam = {};
            var header_key = {
                start: startdate,
                end: enddate
            };
            pam.header_key = JSON.stringify(header_key);
            loadData(projectsele, api + '/ReportAction/GetComBoxProjectCode', true);
            function loadData(selectElement, url, boolean) {
                $.ajax({
                    type: "POST",
                    url: url,
                    data: pam,
                    async: false,
                    dataType: "json",
                    success: function (data) {
                        selectdata = data.ReturnData;
                        selectElement.empty();
                        if (selectdata.length <= 0) {
                            var option = "<option>@Html.Raw(Label.No + Label.Correlation + Label.Data)</option>";
                            selectElement.append(option);
                            return;
                        }
                        if (boolean) {
                            selectElement.append("<option value=''>@Html.Raw(Label.PleaseSelect)...</option>");
                        } else {
                            selectElement.append("<option value='ALL'>@Html.Raw(Label.ALL)</option>");
                        }
                        $.each(selectdata, function (key, value) {
                            selectElement.append($('<option>', {
                                value: value.value,
                                text: value.text
                            }));
                        });
                    }
                });
            }
            $('#cmb_projcode').val('NCCSAD').trigger('change');
            getdate();
        });
        
        var Tab;
        var getdate = function () {
            var startdate = $("#startdate").val();
            var enddate = $("#enddate").val();
            if (startdate <= enddate) {
                var header_key = {
                    start: startdate,
                    end: enddate
                };
                var pam = {};
                pam.proj_code = $('#cmb_projcode').val();
                pam.header_key = JSON.stringify(header_key);
                pam.type = $('#cmb_site').val();
                loadingshow();
                $.ajax({
                    type: "POST",
                    url: api + "/ReportAction/GetYieldAnalysisReport",
                    data: pam,
                    dataType: "json",
                    async: true,
                    success: function (dt) {
                        loadingnone();
                        Tab = dt.ReturnData;
                        reportfunction ("prime_yield");
                        reportfunction ("final_yield");
                        reportfunction ("gap_yield");
                    }
                });
            }
        }
        
        var reportfunction = function(tableid) {
            var data,idelement;
            data = Tab.Table.filter(item => item.DATA_TYPE.toLowerCase() === tableid.toLowerCase());
            var filteredData = data.map(function(item) {
                const result = {};
                for (var key in item) {
                    if (item.hasOwnProperty(key) && key !== 'DATA_TYPE' && key !== 'SORT') {
                        const newKey = key === 'PROCESS_ID' ? tableid.toUpperCase() : key;
                        result[newKey] = item[key];
                    }
                }
                return result;
            });
            var chartid,charttitle
            switch (tableid.toLowerCase()) {
                case "prime_yield":
                    idelement = $("#prime_table");
                    chartid ="prime_chart";
                    charttitle ="Prime Yield Chart";
                    break;
                case "final_yield":
                    idelement = $("#final_table");
                    chartid ="final_chart";
                    charttitle ="Final Yield Chart";
                    break;
                case "gap_yield":
                    idelement = $("#gap_table");
                    chartid ="gap_chart";
                    charttitle ="Gap Yield Chart";
                    break;
            }
            tablereport(filteredData,idelement,tableid);
            renderYieldChart({
                chartId: chartid,
                title: charttitle,
                tableId: tableid.toLowerCase(),
                data: filteredData
            });
        }

        function calculateYieldProduct(tableid) {
            const $table = $(`#${tableid}_grid`);
            const $rows = $table.find('tbody tr');
            if ($rows.length === 0) return;

            const colCount = $rows.first().find('td').length;
            const resultRow = ['<td style="background-color: #ffddc4;">汇总</td>'];
            for (let col = 1; col < colCount; col++) {
                let product = 1;
                let validCount = 0;
                $rows.each(function () {
                    const cellText = $(this).find(`td:eq(${col})`).text().replace('%', '').trim();
                    const value = parseFloat(cellText);
                    if (!isNaN(value) && value > 0) {
                        product *= (value / 100);
                        validCount++;
                    }
                });
                const finalYield = validCount > 0 ? (product * 100).toFixed(2) + '%' : '-';
                resultRow.push(`<td>${finalYield}</td>`);
            }
            const $tfoot = $table.find('tfoot');
            $tfoot.empty();
            $tfoot.append(`<tr>${resultRow.join('')}</tr>`);
        }

        function calculateGapYieldSummary() {
            const gapTable = $('#gap_yield_grid');
            const primeRow = $('#prime_yield_grid tfoot tr td');
            const finalRow = $('#final_yield_grid tfoot tr td');
            if (primeRow.length === 0 || finalRow.length === 0) return;

            const resultRow = ['<td style="background-color: #ffddc4;">汇总</td>'];
            for (let i = 1; i < primeRow.length; i++) {
                const prime = parseFloat(primeRow.eq(i).text().replace('%', '') || '0');
                const final = parseFloat(finalRow.eq(i).text().replace('%', '') || '0');
                const gap = (final - prime).toFixed(2) + '%';
                resultRow.push(`<td>${gap}</td>`);
            }
            const tfoot = gapTable.find('tfoot');
            tfoot.empty();
            tfoot.append(`<tr>${resultRow.join('')}</tr>`);
        }

        function calculateGapAchievementRate() {
            const $table = $('#gap_yield_grid');
            const $rows = $table.find('tbody tr');
            if ($rows.length === 0) return;

            const $tfoot = $table.find('tfoot');
            const colCount = $table.find('thead th').length;

            $rows.each(function () {
                $(this).find('td').removeClass('cell-warn');
            });

            let allTargetsFilled = true;
            $rows.each(function () {
                const $input = $(this).find('input.gap-target');
                if ($input.length === 0 || $input.val().trim() === '') {
                    allTargetsFilled = false;
                }
            });
            if (!allTargetsFilled) {
                console.log('部分目标值未填写，跳过达成率计算');
                return;
            }

            const resultRow = ['<td style="background-color: #ffddc4;">Gap工序达成率</td>'];

            for (let colIndex = 1; colIndex < colCount - 1; colIndex++) {
                let reachCount = 0;
                let validCount = 0;

                $rows.each(function () {
                    const $cells = $(this).find('td');
                    if ($cells.length < colCount) return;

                    const gapCell = $cells.eq(colIndex);
                    const gapText = gapCell.text().replace('%', '').trim();
                    const gapVal = parseFloat(gapText);

                    const $input = $(this).find('input.gap-target');
                    const targetVal = parseFloat($input.val());

                    if (!isNaN(gapVal) && !isNaN(targetVal)) {
                        validCount++;
                        if (gapVal > targetVal) {
                            gapCell.addClass('cell-warn');
                        } else {
                           reachCount++;
                        }
                    }
                });

                const rateValue = validCount > 0 ? (reachCount / validCount) * 100 : null;
                const rateText = rateValue !== null ? rateValue.toFixed(2) + '%' : '-';
                const tdStyle = rateValue !== null && rateValue < 80 ? ' style="color:red;background-color: #f5fd02;"' : '';
                resultRow.push(`<td${tdStyle}>${rateText}</td>`);

                const $th = $table.find(`thead th:eq(${colIndex})`);
                $th.find('.warn-flag').remove();
                if (rateValue !== null && rateValue < 80) {
                    $th.append('<span class="warn-flag" style="color:red" title="达成率低于80%">⚠</span>');
                }
            }

            $tfoot.find('tr:gt(0)').remove();
            $tfoot.append(`<tr>${resultRow.join('')}</tr>`);

            console.log('gap工序达成率已更新:', resultRow);
            $table.trigger('gap-achievement-updated');
        }

        $(document).on('input', '.gap-target', function () {
            setTimeout(() => calculateGapAchievementRate(), 10);
        });

        $(document).on('keydown', '.gap-target', function (e) {
            if (e.key === 'Enter') {
                e.preventDefault();
                const inputs = $('.gap-target');
                const idx = inputs.index(this);
                if (idx >= 0 && idx < inputs.length - 1) {
                    inputs.eq(idx + 1).focus();
                }
            }
        });

        function tablereport(data, idelement, tableid) {
            if (data.length > 0) {
                idelement.empty();
                let html = `<table id="${tableid}_grid" class="DataSheet" border="1" style="width: 100%; height: 100%;">
                                <thead><tr></tr></thead>
                                <tbody id="${tableid}_tbody"></tbody>
                                <tfoot id="${tableid}_tfoot"></tfoot>
                            </table>`;
                idelement.append(html);

                const table = $(`#${tableid}_grid`);
                const tbody = table.find('tbody');
                const headerRow = table.find('thead tr');
                const headers = Object.keys(data[0]);
                headers.forEach((h, i) => {
                    if (i === 0) {
                        headerRow.append(`<th>${h} <span class="warn-flag" style="color:red" title="双击工序查看详情ℹ️">ℹ️</span></th>`);
                    } else {
                        headerRow.append(`<th>${h}</th>`);
                    }
                });

                if (tableid === 'gap_yield') headerRow.append('<th>Gap Target</th>');

                data.forEach((row, idx) => {
                    let newRow = $(`<tr class="${(idx % 2) ? "ZebraNo" : "ZebraTo"}"></tr>`);
                    newRow.on('dblclick', () => {
                        yielddetail(row[headers[0]]);
                    });
                    headers.forEach(h => {
                        const value = row[h];
                        const tdClass = typeof value === 'number' && value < 0 ? 'truncate note' : 'truncate';
                        let displayValue = '';
                        if (typeof value === 'number' && isFinite(value)) {
                            displayValue = value + '%';
                        } else if (typeof value === 'string') {
                            displayValue = value;
                        }
                        newRow.append(`<td class="${tdClass}">${displayValue}</td>`);
                    });
                    if (tableid === 'gap_yield') {
                        newRow.append('<td><input type="number" class="gap-target" style="width: 40px;" /></td>');
                    }
                    tbody.append(newRow);
                });

                if (tableid === 'gap_yield') {
                    calculateGapYieldSummary();
                    calculateGapAchievementRate();
                    $(`#${tableid}_grid`).on('input', '.gap-target', function () {
                        calculateGapAchievementRate();
                    });
                } else {
                    calculateYieldProduct(tableid);
                }
            }
        }

        function renderYieldChart({ chartId, title, tableId, data }) {
            const chartDom = document.getElementById(chartId);
            if (echarts.getInstanceByDom(chartDom)) {
                echarts.dispose(chartDom);
            }
            const chart = echarts.init(chartDom);
            const renamedKey = tableId.toUpperCase();
            const allKeys = Object.keys(data[0]);
            const year = $("#startdate").val().slice(0, 4);

            const dateKeys = allKeys
                .filter(k => /^\d{1,2}\/\d{1,2}$/.test(k))
                .sort((a, b) => new Date(`${year}/${a}`) - new Date(`${year}/${b}`));

            const $tfootCells = $(`#${tableId}_grid tfoot tr:first td`);
            const summarySeries = {
                name: '汇总',
                type: 'line',
                smooth: true,
                lineStyle: { width: 3, color: 'red' },
                itemStyle: { color: 'red' },
                data: dateKeys.map((date, i) => {
                    const text = $tfootCells.eq(i + 1).text().replace('%', '');
                    const val = parseFloat(text);
                    return isNaN(val) ? null : val;
                })
            };

            const series = data.map(item => ({
                name: item[renamedKey],
                type: 'line',
                smooth: true,
                data: dateKeys.map(date => item[date] != null ? item[date] : null)
            }));
            series.unshift(summarySeries);

            const option = {
                title: { show: false, text: title, left: 'center' },
                tooltip: {
                    trigger: 'axis',
                    valueFormatter: val => val != null ? val.toFixed(2) + '%' : '-'
                },
                toolbox: {
                    feature: {
                        restore: { show: true },
                        saveAsImage: { show: true, name: `${chartId}`}
                    }
                },
                legend: { type: 'scroll', top: 'bottom' ,selectedMode: 'multiple' },
                xAxis: { type: 'category', data: dateKeys },
                yAxis: {
                    type: 'value',
                    name: title,
                    scale: true,
                    nameTextStyle: { fontWeight: 'bold', color: '#000' },
                    axisLabel: { formatter: '{value}%' }
                },
                grid: { top: 40, bottom: 60, left: 60, right: 15 },
                series,
                dataZoom: [
                    { type: 'inside', yAxisIndex: 0 },
                    { type: 'slider', yAxisIndex: 0, right: 1, width: 10 }
                ]
            };
            chart.setOption(option);
            chart.on('legendselectchanged', function (params) {
                console.log("1111");
                const clickedLegend = params.name;
                const currentOption = chart.getOption();
                const selected = {};
                const onlySelected =
                Object.entries(params.selected).filter(([_, v]) => v).length === 1 &&
                params.selected[clickedLegend];

                const legendData = series.map(s => s.name);

                if (onlySelected) {
                    legendData.forEach(name => selected[name] = true);
                } else {
                    legendData.forEach(name => selected[name] = name === clickedLegend);
                }
                currentOption.legend[0].selected = selected;
                chart.setOption(currentOption, false);
            });
            window.addEventListener('resize', () => chart.resize());
        }

        //yielddetail
        function yielddetail(process)
        {
            var projcode = $('#cmb_projcode option:selected').text();
            $(".process_name").text(`${$('#cmb_site').val()}：${projcode}：${process}`);
            var startdate = $("#startdate").val();
            var enddate = $("#enddate").val();
            var header_key = {start: startdate,end: enddate};
            var pam = {};
            pam.proj_code = $('#cmb_projcode').val();
            pam.process_id = process;
            pam.header_key = JSON.stringify(header_key);
            pam.type = $('#cmb_site').val();
            $.ajax({
                type: "POST",
                url: api + "/ReportAction/GetYieldDetail",
                data: pam,
                dataType: "json",
                async: false,
                success: function (dt) {
                    var data = dt.ReturnData.Table;
                    if (data.length>0)
                    {
                        //console.log(JSON.stringify(data));
                        $(".mode_confirm").css("display", "block");
                        inputchart(process,data);
                        failuremodechart(process,data);
                        testeryield(process,dt.ReturnData.Table1);
                        //reportdetail(data);
                    }
                }
            });
        }

        function reportdetail (data)
        {
            var defect_table_html = `
            <table id="defect_detail" style="margin: 0rem 0.15rem 0.15rem 0.15rem;width: calc(100% - 0.3rem);">
                <thead><tr></tr></thead>
                <tbody></tbody>
            </table>`;
            $(".mode_detail").append(defect_table_html);
            var table = $('#defect_detail');
            var tbody = table.find('tbody');
            var headerRow = table.find('thead tr');
            var headers = Object.keys(data[0]);
            headers.forEach(function (header) {
                headerRow.append('<th>' + header + '</th>');
            });
            var braNo = "style='text-align:center;background-color:#ffffff;'";
            var braTo = "style='text-align:center;background-color:#d2e9f8;'";
            data.forEach(function (row, index) {
                index++;
                var newRow = $(`<tr></tr>`);
                var style = (index % 2) > 0 ? braNo : braTo;
                headers.forEach(function (header, columnindex) {
                    newRow.append(`<td ${style} class="truncate">${row[header]}</td>`);
                });
                tbody.append(newRow);
            });
        }

        function inputchart(process,data)
        {
            var projcode = $('#cmb_projcode option:selected').text();
            const chartDom = document.getElementById('inputchart');
            if (chartDom) {
                echarts.dispose(chartDom); 
            }
            const myChart = echarts.init(chartDom);
            const seenDate = new Set();
            const stagefpyarray = [];
            data.forEach(row => {
                const date = row.DATE.split('T')[0].replaceAll('-', '');
                if (seenDate.has(date)) return;
                seenDate.add(date);
                const input = row.INPUT_QTY;
                const output = row.OUTPUT_QTY;
                const failure = input - output;
                const fpy = input > 0 ? output / input : 0;
                stagefpyarray.push({
                    DATE_TIME: date,
                    FIRST_INPUT: input,
                    TOTAL_FAILURE: failure,
                    FPY: fpy
                });
            });

            const categories = stagefpyarray.map(item => item.DATE_TIME);
            const firstInput = stagefpyarray.map(item => item.FIRST_INPUT);
            const totalFailure = stagefpyarray.map(item => item.TOTAL_FAILURE);
            const fpy = stagefpyarray.map(item => parseFloat((item.FPY * 100).toFixed(2)));
            //设置图表
            myChart.setOption({
                title: {
                    text: `${projcode} ${process} Input Chart`,
                    left: 'center',
                    textStyle: {
                        fontSize: '0.2rem',
                        fontWeight: 'bold'
                    }
                },
                tooltip: {
                    trigger: 'axis',
                    axisPointer: { type: 'cross' }
                },
                toolbox: {
                    feature: {
                        dataView: { show: true, readOnly: false },
                        magicType: { show: true, type: ['line', 'bar'] },
                        restore: { show: true },
                        saveAsImage: {
                            show: true,
                            name: `${projcode}_${process}_Input_Chart`
                        }
                    }
                },
                legend: {
                    top: '10%',
                    data: ['FIRST_INPUT', 'TOTAL_FAILURE', 'FPY'],
                    textStyle: {
                        fontSize: '0.16rem',
                        fontWeight: 'bold'
                    }
                },
                grid: {
                    left: '4%',
                    right: '4%'
                },
                xAxis: {
                    type: 'category',
                    data: categories,
                    axisLabel: { rotate: 45 }
                },
                yAxis: [
                {
                    type: 'value',
                    name: 'Input',
                    position: 'left',
                    yAxisIndex: 0,
                    splitLine: { show: false }
                },
                {
                    type: 'value',
                    name: 'FPY(%)',
                    position: 'right',
                    yAxisIndex: 1,
                    min: 0,
                    max: 100,
                    axisLabel: {
                        formatter: '{value}%'
                    }
                }],
                dataZoom: [
                    {
                        type: 'inside',
                        yAxisIndex: 1,
                        zoomLock: false
                    },
                    {
                        type: 'slider',
                        yAxisIndex: 1,
                        zoomLock: false,
                        right: 1,
                        width: 10
                    }
                ],
                series: [
                {
                    name: 'FIRST_INPUT',
                    type: 'bar',
                    data: firstInput,
                    barWidth: '30%'
                },
                {
                    name: 'TOTAL_FAILURE',
                    type: 'bar',
                    data: totalFailure,
                    barWidth: '30%'
                },
                {
                    name: 'FPY',
                    type: 'line',
                    yAxisIndex: 1,
                    smooth: false,
                    lineStyle: {
                        width: 3,
                        color: '#FFA500'
                    },
                    itemStyle: {
                        color: '#FFA500',
                        borderWidth: 2,
                        borderColor: '#FF4500'
                    },
                    symbolSize: 8,
                    data: fpy,
                    tooltip: {
                        valueFormatter: (value) => value.toFixed(2) + '%'
                    }
                }]
            });
            window.addEventListener('resize', () => {
                myChart.resize();
            });
        }

        function failuremodechart(process,data)
        {
            var projcode = $('#cmb_projcode option:selected').text();
            const failureModeMap = new Map();
            const xAxisSet = new Set();
            data.forEach(row => {
                const date = row.DATE.split('T')[0].replaceAll('-', '');
                xAxisSet.add(date);
                const mode = row.FAILURE_MODE || 'UNKNOWN';
                if (!failureModeMap.has(mode)) failureModeMap.set(mode, []);
                failureModeMap.get(mode).push({
                dateTime: date,
                failRate: parseFloat(row.PRIME_REJECT_RATE)
                });
            });
            const xAxisData = Array.from(xAxisSet).sort((a, b) => a.localeCompare(b, undefined, { numeric: true }));
            const sortedEntries = Array.from(failureModeMap.entries()).sort((a, b) => {
                const avgA = a[1].reduce((sum, v) => sum + parseFloat(v.failRate), 0) / a[1].length;
                const avgB = b[1].reduce((sum, v) => sum + parseFloat(v.failRate), 0) / b[1].length;
                return avgB - avgA;
            });
            const sortedFailureModeMap = new Map(sortedEntries);
            const colors = ['#ff0000', '#efdf00', '#00008b', '#6b8e23', '#008b8b', '#ff00ff', '#ff8c00', '#4682b4', '#8031a7', '#a0522d'];
            let index = 0;
            const seriesData = [];
            const generateGradientColors = (baseColor) => [
                echarts.color.lift(baseColor, 0.4),
                echarts.color.lift(baseColor, -0.4)
            ];
            sortedFailureModeMap.forEach((values, failureMode) => {
                const colorGradient = generateGradientColors(colors[index % colors.length]);
                const dataMap = new Map(values.map(item => [item.dateTime, item.failRate]));
                const failRates = xAxisData.map(date => dataMap.get(date) || "0.00");
                seriesData.push({
                    name: failureMode,
                    type: 'line',
                    stack: 'total',
                    smooth: false,
                    showSymbol: false,
                    emphasis: { focus: 'series' },
                    lineStyle: {
                      width: 0,
                      color: colors[index % colors.length]
                    },
                    itemStyle: {
                      color: colors[index % colors.length]
                    },
                    areaStyle: {
                      opacity: 0.8,
                      color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
                        { offset: 0, color: colorGradient[0] },
                        { offset: 1, color: colorGradient[1] }
                      ])
                    },
                    data: failRates
                });
              index++;
          });
          const chartDom = document.getElementById('failuremodechart');
          echarts.dispose(chartDom);
          const myChart = echarts.init(chartDom);
          myChart.setOption({
              title: {
                  text: `${projcode} ${process} Failure Mode Chart`,
                  left: 'center',
                  textStyle: {
                      fontSize: '0.2rem',
                      fontWeight: 'bold'
                  }
              },
              tooltip: {
                  trigger: 'axis',
                  axisPointer: { type: 'line' },
                  formatter: function (params) {
                      let validParams = params.filter(p => parseFloat(p.value) > 0);
                      if (validParams.length === 0) return '';
                      validParams.sort((a, b) => parseFloat(b.value) - parseFloat(a.value));
                      let tooltipHtml = `<div style="padding: 2px 8px; text-align: left;"><strong>注：Tooltip 仅显示大于 0% 的数据</strong></div>`;
                      tooltipHtml += `<table style="border-collapse: collapse; width: 100%;">` +
                      validParams.map(p => `
                      <tr>
                         <td style="padding: 2px 8px; text-align: left;">${p.marker} <strong>${p.seriesName}</strong></td>
                         <td style="padding: 2px 8px; text-align: right;"><strong>${p.value}%</strong></td>
                      </tr>
                      `).join('') + `</table>`;
                      return tooltipHtml;
                  }
              },
              toolbox: {
                  feature: {
                      dataView: { show: true, readOnly: false },
                      magicType: { show: true, type: ['bar'] },
                      restore: { show: true },
                      saveAsImage: {
                          show: true,
                          name: `${projcode}_${process}_Failure_Mode_Chart`
                      }
                  }
              },
              legend: {
                  show: true,
                  top: '10%',
                  type: 'scroll',
                  width: '98%',
                  data: Array.from(sortedFailureModeMap.keys()),
                  orient: 'horizontal',
                  itemWidth: 12,
                  itemHeight: 12,
                  scrollDataIndex: 0,
                  pageIconSize: [16, 16],
                  pageIconColor: '#0aa9cd',
                  pageTextStyle: {
                      fontSize: '0.16rem'
                  },
                  textStyle: {
                      fontSize: '0.16rem',
                      fontWeight: 'bold'
                  }
              },
              grid: {
                  left: '4%',
                  right: '3%'
              },
              xAxis: {
                  type: 'category',
                  data: xAxisData,
                  axisLabel: { rotate: 45 }
              },
              yAxis: {
                  type: 'value',
                  scale: true,
                  axisLabel: {
                      formatter: '{value}%'
                  }
              },
              series: seriesData
          });
          window.addEventListener('resize', () => {
              myChart.resize();
          });
        }

        function testeryield(process, data) 
        {
            let testerYieldArray = [];
            let processedKeys = new Set();
            data.forEach(item => {
                let date = item.DATE.split('T')[0].replaceAll('-', '');
                let testerDateKey = `${item.TESTER}_${date}`;
                if (!processedKeys.has(testerDateKey)) {
                    testerYieldArray.push({
                        TESTER: item.TESTER,
                        DATE: date,
                        PRIME_YIELD: parseFloat(item.PRIME_YIELD.replace('%', '')) || 0
                    });
                    processedKeys.add(testerDateKey);
                }
            });

            let chartDom = document.getElementById('testeryieldchart');
            if (chartDom) {
                echarts.dispose(chartDom);
            }
            let myChart = echarts.init(chartDom);

            let testerMap = new Map();
            let xAxisSet = new Set();

            testerYieldArray.forEach(item => {
                xAxisSet.add(item.DATE);
                if (!testerMap.has(item.TESTER)) {
                    testerMap.set(item.TESTER, []);
                }
                testerMap.get(item.TESTER).push({ date: item.DATE, yield: item.PRIME_YIELD.toFixed(2) });
            });

            let sortedTesterEntries = Array.from(testerMap.entries()).map(([tester, values]) => {
                let avg = values.reduce((sum, v) => sum + parseFloat(v.yield), 0) / values.length;
                return { tester, values, avg };
            }).sort((a, b) => a.avg - b.avg);

            let sortedTesterMap = new Map();
            sortedTesterEntries.forEach(entry => {
                sortedTesterMap.set(entry.tester, entry.values);
            });

            let xAxisData = Array.from(xAxisSet).sort();

            let seriesData = [];
            const colors = ['#ff0000', '#efdf00', '#00008b', '#6b8e23', '#008b8b', '#ff00ff', '#ff8c00', '#4682b4', '#8031a7', '#a0522d'];
            let index = 0;
            sortedTesterMap.forEach((values, tester) => {
                let dataMap = new Map(values.map(item => [item.date, item.yield]));
                let yieldValues = xAxisData.map(date => dataMap.get(date) || null);

                seriesData.push({
                    name: tester,
                    type: 'line',
                    data: yieldValues,
                    emphasis: {
                        focus: 'series',
                        lineStyle: { opacity: 1 },
                        itemStyle: { opacity: 1 }
                    },
                    label: {
                        show: false,
                        formatter: params => `${params.value || 0}%`
                    },
                    lineStyle: {
                        color: colors[index % colors.length],
                        width: 3
                    },
                    itemStyle: {
                        color: colors[index % colors.length],
                        borderWidth: 2
                    },
                    symbolSize: 8
                });
                index++;
            });

            const option = {
                title: {
                    text: `${process} Tester Yield Chart`,
                    left: 'center',
                    textStyle: {
                        fontSize: '0.2rem',
                        fontWeight: 'bold'
                    }
                },
                tooltip: {
                    trigger: 'item',
                    valueFormatter: value => `${value}%`
                },
                toolbox: {
                    feature: {
                        dataView: { show: true, readOnly: false },
                        restore: { show: true },
                        saveAsImage: {
                            show: true,
                            name: `${process}_Tester_Yield_Chart`
                        }
                    }
                },
                legend: {
                    show: true,
                    type: 'scroll',
                    top: '10%',
                    width: '98%',
                    data: Array.from(sortedTesterMap.keys()),
                    orient: 'horizontal',
                    itemWidth: 12,
                    itemHeight: 12,
                    scrollDataIndex: 0,
                    pageIconSize: [16, 16],
                    pageIconColor: '#0aa9cd',
                    pageTextStyle: {
                        fontSize: '0.16rem'
                    },
                    textStyle: {
                        fontSize: '0.16rem',
                        fontWeight: 'bold'
                    }
                },
                grid: {
                    left: '4%',
                    right: '3%'
                },
                xAxis: {
                    type: 'category',
                    data: xAxisData,
                    axisLabel: {
                        rotate: 45
                    }
                },
                yAxis: {
                    type: 'value',
                    scale: true,
                    axisLabel: {
                        formatter: '{value}%'
                    }
                },
                series: seriesData,
                dataZoom: [
                    {
                        type: 'inside',
                        yAxisIndex: 0,
                        zoomLock: false
                    },
                    {
                        type: 'slider',
                        yAxisIndex: 0,
                        zoomLock: false,
                        right: 1,
                        width: 10
                    }
                ]
            };
            myChart.setOption(option);
            window.addEventListener('resize', () => {
                myChart.resize();
            });
        }

        const tables = document.querySelectorAll('.table');
        tables.forEach((table) => {
          table.addEventListener('scroll', () => {
            const scrollLeft = table.scrollLeft;
            const scrollTop = table.scrollTop;
            tables.forEach((t) => {
              if (t !== table) {
                t.scrollLeft = scrollLeft;
                t.scrollTop = scrollTop;
              }
            });
          });
        });

    </script>
</body>
</html>